"""
玩家类模块，管理每个玩家的游戏状态。
"""
import random
from typing import Dict, List, Tuple, Optional

import pygame

from tetris.board import Board
from tetris.tetromino import Tetromino
from tetris.constants import (
    BOARD_WIDTH, BOARD_HEIGHT, INITIAL_FALL_SPEED,
    LEVEL_SPEEDUP_FACTOR, SHAPES, COLORS
)


class Player:
    """表示游戏中的一个玩家"""
    
    # 类变量，用于共享随机种子
    _shared_random_seed = 42
    _shared_random_initialized = False
    
    @classmethod
    def _get_next_shape_type(cls) -> str:
        """获取下一个形状类型，确保两个玩家获得相同的序列"""
        if not cls._shared_random_initialized:
            random.seed(cls._shared_random_seed)
            cls._shared_random_initialized = True
            
        return random.choice(list(SHAPES.keys()))
    
    def __init__(self, player_id: int, controls: Dict[str, str], start_x: int, create_tetromino: bool = True):
        """
        初始化玩家
        
        Args:
            player_id: 玩家ID(1或2)
            controls: 控制键映射
            start_x: 游戏板在屏幕上的X坐标起点
            create_tetromino: 是否立即创建方块，菜单状态下应为False
        """
        self.player_id = player_id
        self.board = Board()
        self.controls = controls
        self.start_x = start_x
        
        # 重要: 确保游戏板是真正空的
        self.board.grid = [[None for _ in range(BOARD_WIDTH)] for _ in range(BOARD_HEIGHT)]
        
        # 游戏状态
        self.fall_speed = INITIAL_FALL_SPEED
        self.fall_timer = 0
        self.game_over = False
        
        # 只有在需要时才创建方块
        if create_tetromino:
            self.current_tetromino = self._create_tetromino()
            self.next_tetromino = self._create_tetromino()
        else:
            self.current_tetromino = None
            self.next_tetromino = None
        
        # 添加按键延迟变量 - 为不同操作设置不同的延迟
        self.key_timers = {
            'LEFT': 0,
            'RIGHT': 0,
            'DOWN': 0,
            'ROTATE': 0,
            'DROP': 0
        }
        
        # 不同操作的延迟时间设置
        self.key_delays = {
            'LEFT': 0.08,    # 左移动作稍快一些
            'RIGHT': 0.08,   # 右移动作稍快一些
            'DOWN': 0.05,    # 下移可以更快
            'ROTATE': 0.25,  # 旋转延迟明显增加，防止快速连续旋转
            'DROP': 0.3      # 硬降延迟更长，防止误操作
        }
        
        # 添加一个标志和计时器以延迟游戏结束检测
        self.start_grace_period = 2.0  # 游戏开始后2秒内不检测游戏结束
        self.game_time = 0.0
        
    def _create_tetromino(self) -> Tetromino:
        """创建一个新的随机方块 - 完全重写版本"""
        # 使用类方法获取形状类型
        shape_type = self._get_next_shape_type()
        
        # 初始位置更高，避免游戏开始就有方块
        x = BOARD_WIDTH // 2 - 1
        y = -5  # 更高的初始位置
        
        # 创建新方块并验证
        new_tetromino = Tetromino(x, y, shape_type)
        
        # 记录创建信息
        print(f"玩家{self.player_id}创建新方块: {shape_type} 在 ({x}, {y})")
        
        return new_tetromino
    
    def _spawn_next_tetromino(self) -> None:
        """生成下一个方块"""
        self.current_tetromino = self.next_tetromino
        self.next_tetromino = self._create_tetromino()
        
        # 检查游戏是否结束
        if not self.board.is_valid_position(self.current_tetromino):
            self.game_over = True
    
    def update(self, dt: float, keys_pressed: Dict[int, bool]) -> None:
        """更新玩家游戏状态"""
        if self.game_over:
            return
        
        # 更新游戏时间
        self.game_time += dt
        
        # 计算当前级别的下落速度
        current_speed = self.fall_speed * (LEVEL_SPEEDUP_FACTOR ** (self.board.level - 1))
        
        # 更新下落计时器
        self.fall_timer += dt
        
        # 只有当玩家1在关键时刻才输出调试信息
        if self.player_id == 1 and int(self.fall_timer * 10) % 50 == 0:
            print(f"Player {self.player_id}: pos=({self.current_tetromino.x}, {self.current_tetromino.y}), type={self.current_tetromino.shape_type}")
        
        # 下落逻辑
        if self.fall_timer >= 1.0 / current_speed:
            self.fall_timer = 0
            # 保存下落前位置用于调试
            old_y = self.current_tetromino.y
            self._move_down()
            # 输出下落结果
            if self.player_id == 1:
                if old_y == self.current_tetromino.y:
                    print(f"Player {self.player_id}: 方块已固定在位置 y={old_y}")
                else:
                    print(f"Player {self.player_id}: 方块下落从 y={old_y} 到 y={self.current_tetromino.y}")
        
        # 处理玩家输入
        if self.current_tetromino:
            self._handle_input(keys_pressed, dt)
    
    def _handle_input(self, keys_pressed: Dict[int, bool], dt: float) -> None:
        """
        处理玩家输入
        
        Args:
            keys_pressed: 按键状态字典
            dt: 时间增量(秒)
        """
        # 将字符串控制键转换为pygame键值
        key_map = {
            'left': pygame.K_LEFT,
            'right': pygame.K_RIGHT,
            'up': pygame.K_UP,
            'down': pygame.K_DOWN,
            'a': pygame.K_a,
            'd': pygame.K_d,
            'w': pygame.K_w,
            's': pygame.K_s,
            'space': pygame.K_SPACE,
            'return': pygame.K_RETURN
        }
        
        # 更新所有键的计时器
        for key in self.key_timers:
            if self.key_timers[key] > 0:
                self.key_timers[key] -= dt
        
        # 左移
        left_key = key_map.get(self.controls['LEFT'])
        if left_key is not None and keys_pressed[left_key] and self.key_timers['LEFT'] <= 0:
            self._move_horizontal(-1)
            self.key_timers['LEFT'] = self.key_delays['LEFT']
            
        # 右移
        right_key = key_map.get(self.controls['RIGHT']) 
        if right_key is not None and keys_pressed[right_key] and self.key_timers['RIGHT'] <= 0:
            self._move_horizontal(1)
            self.key_timers['RIGHT'] = self.key_delays['RIGHT']
            
        # 下移
        down_key = key_map.get(self.controls['DOWN'])
        if down_key is not None and keys_pressed[down_key] and self.key_timers['DOWN'] <= 0:
            self._move_down()
            self.key_timers['DOWN'] = self.key_delays['DOWN']
            
        # 旋转 - 使用更长的延迟
        rotate_key = key_map.get(self.controls['ROTATE'])
        if rotate_key is not None and keys_pressed[rotate_key] and self.key_timers['ROTATE'] <= 0:
            self._rotate()
            self.key_timers['ROTATE'] = self.key_delays['ROTATE']
            
        # 直接下落 - 同样使用延迟
        drop_key = key_map.get(self.controls['DROP'])
        if drop_key is not None and keys_pressed[drop_key] and self.key_timers['DROP'] <= 0:
            self._hard_drop()
            self.key_timers['DROP'] = self.key_delays['DROP']
    
    def _move_horizontal(self, dx: int) -> None:
        """水平移动当前方块"""
        if not self.current_tetromino:
            return
            
        self.current_tetromino.move(dx, 0)
        
        # 如果移动后位置无效，则移回原位置
        if not self.board.is_valid_position(self.current_tetromino):
            self.current_tetromino.move(-dx, 0)
    
    def _move_down(self) -> None:
        """向下移动当前方块"""
        if not self.current_tetromino:
            return
        
        # 尝试向下移动
        self.current_tetromino.move(0, 1)
        
        # 如果移动后位置无效，则固定当前方块
        if not self.board.is_valid_position(self.current_tetromino):
            # 移回原位置
            self.current_tetromino.move(0, -1)
            
            # 检查是否完全在屏幕外（游戏刚开始）
            if self.current_tetromino.y < 0:
                print(f"警告：玩家{self.player_id}的方块在屏幕外固定")
                # 强制继续下移直到至少部分可见
                self.current_tetromino.move(0, 1)
                return
            
            # 添加到游戏板
            print(f"玩家{self.player_id}固定方块：{self.current_tetromino.shape_type} 在 y={self.current_tetromino.y}")
            self.board.add_tetromino(self.current_tetromino)
            
            # 清除行并生成新方块
            lines_cleared = self.board.clear_lines()
            if lines_cleared > 0:
                print(f"玩家{self.player_id}清除了{lines_cleared}行！")
            
            self._spawn_next_tetromino()
    
    def _rotate(self) -> None:
        """旋转当前方块 - 修复版"""
        if not self.current_tetromino:
            return
        
        # 保存旧的旋转状态以便回退
        old_rotation = self.current_tetromino.rotation
        
        # 执行旋转
        self.current_tetromino.rotate()
        
        # 获取方块形状的总旋转状态数
        total_rotations = len(self.current_tetromino.shape)
        
        # 如果旋转后位置无效，尝试多达4次旋转
        if not self.board.is_valid_position(self.current_tetromino):
            # 重置到原来的旋转状态
            self.current_tetromino.rotation = old_rotation
            
            # 逆向旋转回去
            # self.current_tetromino.rotate(False)  # 逆向旋转回去
            
            print(f"旋转失败：形状={self.current_tetromino.shape_type}, 旋转={old_rotation}/{total_rotations}")
    
    def _hard_drop(self) -> None:
        """方块直接下落到底部"""
        if not self.current_tetromino:
            return
            
        # 不断向下移动直到碰到底部
        while self.board.is_valid_position(self.current_tetromino):
            self.current_tetromino.move(0, 1)
        
        # 回退一步（因为最后一次移动是无效的）
        self.current_tetromino.move(0, -1)
        
        # 固定方块并生成新方块
        self.board.add_tetromino(self.current_tetromino)
        self.board.clear_lines()
        self._spawn_next_tetromino() 